package com.org.oracle.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Preconditions;
import com.org.oracle.constant.TaskConstants;
import com.org.oracle.enums.ResponseCodeEnum;
import com.org.oracle.exception.CustomException;
import com.org.oracle.mapper.TaskMapper;
import com.org.oracle.mysql.dto.TaskAcceptDTO;
import com.org.oracle.mysql.dto.TaskInitDTO;
import com.org.oracle.mysql.entity.Task;
import com.org.oracle.service.StudyPointsListService;
import com.org.oracle.service.TaskListService;
import com.org.oracle.service.TaskService;

import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @author heiye
 * @version 1.0
 * @data 2024/8/19 下午5:27
 */
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
    @Resource
    private TransactionTemplate transactionTemplate;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private TaskListService taskListService;

    @Autowired
    private StudyPointsListService studyPointsListService;

    /**
     * 用户 加入知识圈 任务初始化
     */
    @Override
    public void taskInit(String uid, TaskInitDTO dto) {
        // 检查参数
        Preconditions.checkArgument(StringUtils.isNotBlank(uid) && Objects.nonNull(dto), ResponseCodeEnum.PARAM_REQUIRE);
        // 检查dto里的参数
        Preconditions.checkArgument(dto.checkParam(), ResponseCodeEnum.PARAM_REQUIRE);

        // 初始化用户id，任务状态
        Task task = Task.builder()
                .uid(uid)
                .points(0)
                .state(TaskConstants.NOT_CHALLENGED)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();

        // 将剩余字段初始化
        BeanUtils.copyProperties(dto, task);

        // 添加数据
        taskMapper.insert(task);
    }

    /**
     * 查找用户在该知识圈下的学习任务进度
     */
    @Override
    public List<Task> taskProgress(String uid, String circleId) {
        // 检查参数
        Preconditions.checkArgument(StringUtils.isNotBlank(uid) && StringUtils.isNotBlank(circleId), ResponseCodeEnum.PARAM_REQUIRE);

        return taskMapper.selectList(Wrappers.<Task>lambdaQuery().eq(Task::getUid, uid).eq(Task::getCircleId, circleId));
    }

    /**
     * 用户接受任务
     *
     * @param uid
     * @param name  任务名称
     * @param state 2:正在挑战
     */
    @Override
    public void taskChallenge(String uid, String name, Integer state) {
        transactionTemplate.execute(status -> {
            try {
                // 检查参数
                Preconditions.checkArgument(StringUtils.isNotBlank(uid) && StringUtils.isNotEmpty(name), ResponseCodeEnum.PARAM_REQUIRE);
                // 检验任务状态
                Preconditions.checkArgument(TaskConstants.CHALLENGED.equals(state), ResponseCodeEnum.PARAM_INVALID);

                // 找到用户下对应的任务修改状态
                taskMapper.update(Wrappers.<Task>lambdaUpdate()
                        .eq(Task::getUid, uid).eq(Task::getName, name)
                        .set(Task::getState, state)
                        .set(Task::getUpdateTime, LocalDateTime.now()));

                // 查找到用户刚修改的任务
                Task task = taskMapper.selectOne(Wrappers.<Task>lambdaQuery().eq(Task::getUid, uid).eq(Task::getName, name));

                // 添加到任务列表中
                taskListService.taskAdd(uid, task);

                return null;
            } catch (Exception e) {
                // 标记事务为回滚
                status.setRollbackOnly();
                log.error("===> 用户接受任务异常", e);

                throw new CustomException(ResponseCodeEnum.SERVER_ERROR);
            }
        });
    }

    /**
     * 用户完成任务
     *
     * @param uid
     * @param dto   任务名称 任务得分
     * @param state 3:已完成
     */
    @Override
    public void taskFinish(String uid, TaskAcceptDTO dto, Integer state) {
        transactionTemplate.execute(status -> {
            try {
                // 检查参数
                Preconditions.checkArgument(StringUtils.isNotBlank(uid) && Objects.nonNull(dto), ResponseCodeEnum.PARAM_REQUIRE);
                // 校验dto里参数
                Preconditions.checkArgument(StringUtils.isNotBlank(dto.getName()), ResponseCodeEnum.PARAM_REQUIRE);
                // 检验任务状态
                Preconditions.checkArgument(TaskConstants.CHALLENGE_ACCOMPLISHED.equals(state), ResponseCodeEnum.PARAM_INVALID);

                // 校验积分
                if (dto.getPoints() < 0) {
                    dto.setPoints(0);
                }

                // 修改用户对应的任务状态以及分数
                taskMapper.update(Wrappers.<Task>lambdaUpdate()
                        .eq(Task::getUid, uid).eq(Task::getName, dto.getName())
                        .set(Task::getState, state).set(Task::getPoints, dto.getPoints())
                        .set(Task::getUpdateTime, LocalDateTime.now()));

                // 查找到用户刚修改的任务
                Task task = taskMapper.selectOne(Wrappers.<Task>lambdaQuery().eq(Task::getUid, uid).eq(Task::getName, dto.getName()));

                // 任务列表完成任务
                taskListService.taskFinish(uid, task);

                // 修改积分
                studyPointsListService.pointsUpdate(uid, task.getCircleId(), dto.getPoints());
                return null;
            } catch (Exception e) {
                // 标记事务为回滚
                status.setRollbackOnly();
                log.error("===> 用户完成任务异常", e);

                throw new CustomException(ResponseCodeEnum.SERVER_ERROR);
            }
        });
    }
}
